package top.lc951.myglide;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;


import java.util.Collections;
import java.util.List;

import top.lc951.myglide.load.Engine;
import top.lc951.myglide.load.engine.GlideExecutor;
import top.lc951.myglide.load.engine.bitmap_recycle.ArrayPool;
import top.lc951.myglide.load.engine.bitmap_recycle.BitmapPoolAdapter;
import top.lc951.myglide.load.engine.bitmap_recycle.LruArrayPool;
import top.lc951.myglide.load.engine.bitmap_recycle.LruBitmapPool;
import top.lc951.myglide.load.engine.cache.DiskCache;
import top.lc951.myglide.load.engine.cache.InternalCacheDiskCacheFactory;
import top.lc951.myglide.load.engine.cache.LruResourceCache;
import top.lc951.myglide.load.engine.cache.MemoryCache;
import top.lc951.myglide.load.engine.cache.MemorySizeCalculator;
import top.lc951.myglide.manager.ConnectivityMonitorFactory;
import top.lc951.myglide.manager.DefaultConnectivityMonitorFactory;
import top.lc951.myglide.request.RequestListener;

public class GlideBuilder {
    private Engine engine;

    private BitmapPool bitmapPool;
    private ArrayPool arrayPool;
    private MemoryCache memoryCache;

    private GlideExecutor sourceExecutor;
    private GlideExecutor diskCacheExecutor;
    private DiskCache.Factory diskCacheFactory;

    private MemorySizeCalculator memorySizeCalculator;
    private ConnectivityMonitorFactory connectivityMonitorFactory;


    @Nullable
    private RequestManagerRetriever.RequestManagerFactory requestManagerFactory;
    private GlideExecutor animationExecutor;
    private boolean isActiveResourceRetentionAllowed;
    @Nullable private List<RequestListener<Object>> defaultRequestListeners;


    void setRequestManagerFactory(@Nullable RequestManagerRetriever.RequestManagerFactory factory) {
        this.requestManagerFactory = factory;
    }

    @NonNull
    Glide build(@NonNull Context context) {
        if (sourceExecutor == null) {
            sourceExecutor = GlideExecutor.newSourceExecutor();
        }

        if (diskCacheExecutor == null) {
            diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
        }

        if (animationExecutor == null) {
            animationExecutor = GlideExecutor.newAnimationExecutor();
        }

        if (memorySizeCalculator == null) {
            memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
        }

        if (connectivityMonitorFactory == null) {
            connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
        }

        if (bitmapPool == null) {
            int size = memorySizeCalculator.getBitmapPoolSize();
            if (size > 0) {
                bitmapPool = new LruBitmapPool(size);
            } else {
                bitmapPool = new BitmapPoolAdapter();
            }
        }

        if (arrayPool == null) {
            arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
        }

        if (memoryCache == null) {
            memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
        }

        if (diskCacheFactory == null) {
            diskCacheFactory = new InternalCacheDiskCacheFactory(context);
        }

        if (engine == null) {
            engine =
                    new Engine(
                            memoryCache,
                            diskCacheFactory,
                            diskCacheExecutor,
                            sourceExecutor,
                            GlideExecutor.newUnlimitedSourceExecutor(),
                            animationExecutor,
                            isActiveResourceRetentionAllowed);
        }

        if (defaultRequestListeners == null) {
            defaultRequestListeners = Collections.emptyList();
        } else {
            defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
        }

        GlideExperiments experiments = glideExperimentsBuilder.build();
        RequestManagerRetriever requestManagerRetriever =
                new RequestManagerRetriever(requestManagerFactory, experiments);

        return new Glide(
                context,
                engine,
                memoryCache,
                bitmapPool,
                arrayPool,
                requestManagerRetriever,
                connectivityMonitorFactory,
                logLevel,
                defaultRequestOptionsFactory,
                defaultTransitionOptions,
                defaultRequestListeners,
                experiments);
    }
}


